// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Facebook

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

char _license[] SEC("license") = "GPL";

struct sample {
    int pid;
    int seq;
    long value;
    char comm[16];
};

struct ringbuf_map {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    /* libbpf will adjust to valid page size */
    __uint(max_entries, 1000);
} ringbuf1 SEC(".maps"),
  ringbuf2 SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
    __uint(max_entries, 4);
    __type(key, int);
    __array(values, struct ringbuf_map);
} ringbuf_arr SEC(".maps") = {
    .values = {
        [0] = &ringbuf1,
        [2] = &ringbuf2,
    },
};

struct {
    __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
    __uint(max_entries, 1);
    __type(key, int);
    __array(values, struct ringbuf_map);
} ringbuf_hash SEC(".maps") = {
    .values = {
        [0] = &ringbuf1,
    },
};

struct sample nosample = {};

/* inputs */
int pid = 0;
int target_ring = 0;
long value = 0;

/* outputs */
long total = 0;
long dropped = 0;
long skipped = 0;

SEC("tp/syscalls/sys_enter_getpgid")
int test_ringbuf(void *ctx)
{
    int cur_pid = bpf_get_current_pid_tgid() >> 32;
    struct sample *sample;
    void *rb;

    if (cur_pid != pid)
        return 0;

    rb = bpf_map_lookup_elem(&ringbuf_arr, &target_ring);
    if (!rb) {
        skipped += 1;
        return 1;
    }

    sample = bpf_ringbuf_reserve(rb, sizeof(*sample), 0);
    if (!sample) {
        dropped += 1;
        return 1;
    }

    sample->pid = pid;
    bpf_get_current_comm(sample->comm, sizeof(sample->comm));
    sample->value = value;

    sample->seq = total;
    total += 1;

    bpf_ringbuf_submit(sample, 0);

    return 0;
}
